#ifndef EPUBZLIB_ZIP_MINIZLIB_HPP
#define EPUBZLIB_ZIP_MINIZLIB_HPP

SJR_NAMESPACE_BEGIN

class EpubZipMiniZlib final : public EpubZipBasic, private EpubZipBasic::OnZipResourcesListener {
public:
  constexpr static int BUFFER_SIZE = 32 * 1024;

  EpubZipMiniZlib() : EpubZipBasic(), mZipCtx(), mZipReaderBuffer() {
    this->registerOnZipResourcesListener(this);
  }

  ~EpubZipMiniZlib() override {
    this->unregisterOnZipResourcesListener(this);
  }

  void compress(std::string const &path) override {
    mZipCtx = zipOpen(path.c_str(), APPEND_STATUS_CREATE);
    if (mZipCtx == nullptr)
      return;

    this->callOnZipResourcesListener();
    zipClose(mZipCtx, nullptr);
  }

private:
  zipFile mZipCtx;
  char mZipReaderBuffer[BUFFER_SIZE];

  void onZipResources(DataSet &dataset, int step) override {
    auto &&retLen = int(0);
    auto &&info   = zip_fileinfo();
    auto &&path   = dataset.native();

    if (zipOpenNewFileInZip(mZipCtx, path, &info, nullptr, 0, nullptr, 0, nullptr, Z_DEFLATED,
          Z_BEST_COMPRESSION) != ZIP_OK)
      return;

    auto &&in = fopen(path, "rb");
    if (in == nullptr)
      return;

    do {
      retLen = fread(mZipReaderBuffer, 1, sizeof(mZipReaderBuffer), in);
      if (retLen > 0)
        zipWriteInFileInZip(mZipCtx, mZipReaderBuffer, retLen);
    } while (retLen > 0);

    fclose(in);
    zipCloseFileInZip(mZipCtx);

    this->callOnZipProcessListener(dataset.name(), step);
  }
};

SJR_NAMESPACE_END

#endif//EPUBZLIB_ZIP_MINIZLIB_HPP
